home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / tw14w12s.zoo / tw14w12s / window.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-08  |  14.2 KB  |  765 lines

  1. /*
  2.  * Copyright 1992 Eric R. Smith. All rights reserved.
  3.  * Redistribution is permitted only if the distribution
  4.  * is not for profit, and only if all documentation
  5.  * (including, in particular, the file "copying")
  6.  * is included in the distribution in unmodified form.
  7.  * THIS PROGRAM COMES WITH ABSOLUTELY NO WARRANTY, NOT
  8.  * EVEN THE IMPLIED WARRANTIES OF MERCHANTIBILITY OR
  9.  * FITNESS FOR A PARTICULAR PURPOSE. USE AT YOUR OWN
  10.  * RISK.
  11.  */
  12. #include <stdlib.h>
  13. #include <gemfast.h>
  14. #include <aesbind.h>
  15. #include <vdibind.h>
  16. #include <osbind.h>
  17. #include <string.h>
  18. #include "xgem.h"
  19.  
  20. #define WF_BEVENT    24
  21.  
  22. #define IM_RESERVE    12345
  23. #define IM_RELEASE    12346
  24.  
  25. /*
  26.  * global variables
  27.  */
  28.  
  29. /* current top window */
  30. WINDOW *gl_topwin;
  31. extern WINDOW *focuswin;
  32.  
  33. /* list of all windows in system */
  34. WINDOW *gl_winlist;
  35.  
  36. /* do we want graf_{grow,shrink}box effects? */
  37. int win_flourishes = 1;
  38.  
  39. /*
  40.  * some dummy functions for windows
  41.  */
  42.  
  43. static void
  44. clear_win(v, x, y, w, h)
  45.     WINDOW *v;
  46.     int x,y,w,h;
  47. {
  48.     int temp[4];
  49.  
  50.     vsf_color(vdi_handle, 0);
  51.     temp[0] = x;
  52.     temp[1] = y;
  53.     temp[2] = x + w - 1;
  54.     temp[3] = y + h - 1;
  55.     v_bar(vdi_handle, temp);
  56.     vsf_color(vdi_handle, 1);
  57. }
  58.  
  59. static void
  60. top_win(w)
  61.     WINDOW *w;
  62. {
  63.     gl_topwin = w;
  64.     wind_set(w->wi_handle, WF_TOP, 0, 0, 0, 0);
  65. }
  66.  
  67. static void
  68. close_win(w)
  69.     WINDOW *w;
  70. {
  71.     destroy_window(w);
  72. }
  73.  
  74. static void
  75. full_win(v)
  76.     WINDOW *v;
  77. {
  78.     int newx, newy, neww, newh;
  79.  
  80.     if (v->flags & WFULLED) {
  81.         wind_get(v->wi_handle, WF_PREVXYWH, &newx, &newy, &neww,
  82.              &newh);
  83.     } else {
  84.         wind_get(v->wi_handle, WF_FULLXYWH, &newx, &newy, &neww,
  85.             &newh);
  86.     }
  87.  
  88.     wind_set(v->wi_handle, WF_CURRXYWH, newx, newy, neww, newh);
  89.     wind_get(v->wi_handle, WF_WORKXYWH, &v->wi_x, &v->wi_y, &v->wi_w,
  90.         &v->wi_h);
  91.  
  92.     v->flags ^= WFULLED;
  93. }
  94.  
  95. static void
  96. move_win(v, x, y, w, h)
  97.     WINDOW *v;
  98.     int x, y, w, h;
  99. {
  100.     int fullx, fully, fullw, fullh;
  101.  
  102.     wind_get(v->wi_handle, WF_FULLXYWH, &fullx, &fully, &fullw, &fullh);
  103.  
  104.     if (w > fullw) w = fullw;
  105.     if (h > fullh) h = fullh;
  106.  
  107.     if (w != fullw || h != fullh)
  108.         v->flags &= ~WFULLED;
  109.  
  110.     wind_set(v->wi_handle, WF_CURRXYWH, x, y, w, h);
  111.     wind_get(v->wi_handle, WF_WORKXYWH, &v->wi_x, &v->wi_y,
  112.         &v->wi_w, &v->wi_h);
  113. }
  114.  
  115. static void
  116. size_win(v, x, y, w, h)
  117.     WINDOW *v;
  118.     int x, y, w, h;
  119. {
  120.     move_win(v, x, y, w, h);
  121. }
  122.  
  123. static void
  124. noslid(w, m)
  125.     WINDOW *w;
  126.     int m;
  127. {
  128. }
  129.  
  130. static int
  131. nokey(w, code)
  132.     WINDOW *w;
  133.     int code;
  134. {
  135.     return 0;
  136. }
  137.  
  138. static int
  139. nomouse(w, clicks, x, y, shift, mbuttons)
  140.     WINDOW *w;
  141.     int clicks, x, y, shift, mbuttons;
  142. {
  143.     return 0;
  144. }
  145.  
  146. static int
  147. iconmouse(v, clicks, x, y, shift, mbuttons)
  148.     WINDOW *v;
  149.     int clicks, x, y, shift, mbuttons;
  150. {
  151.     int w, h;
  152.  
  153.     if (mbuttons) {
  154. /* wait for a little bit */
  155.         evnt_timer(140L);
  156.         graf_mkstate(&x, &y, &mbuttons, &shift);
  157.         if (x < v->wi_x || x > v->wi_x + v->wi_w || y < v->wi_y ||
  158.             y > v->wi_y + v->wi_w)
  159.             return 1;
  160.         if (mbuttons) {        /* button still down */
  161.             wind_update(BEG_MCTRL);
  162.             graf_mouse(FLAT_HAND, 0L);
  163.             wind_get(v->wi_handle, WF_CURRXYWH, &x, &y, &w, &h);
  164.             graf_dragbox(w, h, x, y, xdesk, ydesk, wdesk, hdesk,
  165.                 &x, &y);
  166.             graf_mouse(ARROW, 0L);
  167.             wind_update(END_MCTRL);
  168.             (*v->moved)(v, x, y, w, h);
  169.             return 1;
  170.         }
  171.     }
  172.     (*v->fulled)(v);    /* un-iconify the window */
  173.     return 1;
  174. }
  175.  
  176. /* turn a window into an icon */
  177.  
  178. static void
  179. uniconify_win(v)
  180.     WINDOW *v;
  181. {
  182.     static int mbuf[8];
  183.     int newx, newy, neww, newh;
  184.     int id = appl_find("ICONMGR ");
  185.  
  186.     if (!(v->flags & WICONIFIED)) return;
  187.     if (id >= 0) {
  188.         mbuf[0] = IM_RELEASE;
  189.         mbuf[1] = gl_apid;
  190.         mbuf[2] = 0;
  191.         mbuf[3] = v->icon_slot;
  192.         appl_write(id, 16, mbuf);
  193.     }
  194.     v->fulled = v->oldfulled;
  195.     v->mouseinp = v->oldmouse;
  196.     v->flags &= ~WICONIFIED;
  197.  
  198.     if (win_flourishes) {
  199.         graf_growbox(v->wi_x, v->wi_y, v->wi_w, v->wi_h,
  200.                  v->prevx, v->prevy, v->prevw, v->prevh);
  201.     }
  202.     wind_calc(WC_BORDER, v->old_wkind, v->prevx, v->prevy, v->prevw,
  203.             v->prevh, &newx, &newy, &neww, &newh);
  204.     change_window_gadgets(v, v->old_wkind);
  205.     (*v->sized)(v, newx, newy, neww, newh);
  206.  
  207. /* button events should top the window */
  208.     wind_set(v->wi_handle, WF_BEVENT, 0x0000, 0, 0, 0);
  209.     (*v->topped)(v);
  210. }
  211.  
  212. static void
  213. iconify_win(v, slot, x, y, w, h)
  214.     WINDOW *v;
  215.     int slot, x, y, w, h;
  216. {
  217.     if (v->flags & WICONIFIED)
  218.         return;
  219.     v->flags &= ~WFULLED;
  220.     v->flags |= WICONIFIED;
  221.     v->oldfulled = v->fulled;
  222.     v->oldmouse = v->mouseinp;
  223.     v->icon_slot = slot;
  224.     v->old_wkind = v->wi_kind;
  225.  
  226.     v->prevx = v->wi_x;
  227.     v->prevy = v->wi_y;
  228.     v->prevw = v->wi_w;
  229.     v->prevh = v->wi_h;
  230.     change_window_gadgets(v, 0);
  231.     if (win_flourishes) {
  232.         graf_shrinkbox(x, y, w, h, v->prevx, v->prevy, v->prevw,
  233.                 v->prevh);
  234.     }
  235.     (*v->sized)(v, x, y, w, h);
  236.  
  237. /* we don't want the window topped inadvertently */
  238.     wind_set(v->wi_handle, WF_BEVENT, 0x0001, 0, 0, 0);
  239.     v->fulled = uniconify_win;
  240.     v->mouseinp = iconmouse;
  241.     new_topwin(1);
  242. }
  243.  
  244. /*
  245.  * Create a new window with title "title," initial/full size x, y, w, h,
  246.  * and gadgets given by "kind." Returns a pointer to the new window,
  247.  * or NULL if an error occurs. The window is not actually opened,
  248.  * however.
  249.  */
  250.  
  251. /* used to "stagger" opening positions of windows */
  252. #define WOFF_INC gl_hbox
  253. #define WOFF_MAX 64
  254.  
  255. #ifdef WWA_EXT_TOSRUN
  256. /* BUT, turn it off if TOSRUN pipe supports window positioning! */
  257. # ifdef WWA_WIN_RUN
  258. # undef WOFF_INC gl_hbox
  259. # define WOFF_INC 0
  260. # endif
  261. #endif
  262.  
  263. static int winoff = 0;
  264.  
  265. WINDOW *
  266. create_window(title, kind, wx, wy, ww, wh)
  267.     const char *title;
  268.     int kind, wx, wy, ww, wh;
  269. {
  270.     WINDOW *v;
  271.     int fullx, fully, fullw, fullh;
  272.     int centerwin = 0;
  273.  
  274.     if (title) {
  275.         title = strdup(title);
  276.     }
  277.  
  278.     v = malloc(sizeof(WINDOW));
  279.     if (!v) return v;
  280.  
  281.     v->wi_handle = -1;    /* not open yet */
  282.     v->wi_kind = kind;
  283.  
  284.     if (wx == 0 && wy == 0) centerwin = 1;
  285.     if (wx < xdesk) wx = xdesk;
  286.     if (wy < ydesk) wy = ydesk;
  287.  
  288. /* calculate max. window size needed for a working area of ww x wh */
  289.     wind_calc(WC_WORK, v->wi_kind, wx, wy, wdesk, hdesk,
  290.          &v->wi_x, &v->wi_y, &v->wi_w, &v->wi_h);
  291.     wind_calc(WC_BORDER, v->wi_kind, v->wi_x, v->wi_y, ww, wh,
  292.          &fullx, &fully, &fullw, &fullh);
  293.  
  294.     if (fullw > wdesk)
  295.         fullw = wdesk;
  296.     if (fullh > hdesk)
  297.         fullh = hdesk;
  298.  
  299.     if (centerwin) {
  300.         fullx = xdesk;
  301.         fully = ydesk;
  302.     }
  303.  
  304.  
  305.     fullx += winoff;
  306.     fully += winoff;
  307.     winoff += WOFF_INC;
  308.     if (winoff > WOFF_MAX) {
  309.         winoff = 0;
  310.     }
  311.  
  312.     v->wi_title = (char *)title;
  313.     v->wi_fullx = fullx;
  314.     v->wi_fully = fully;
  315.     v->wi_fullw = fullw;
  316.     v->wi_fullh = fullh;
  317.  
  318.     wind_calc(WC_WORK, v->wi_kind, fullx, fully, fullw, fullh,
  319.           &v->wi_x, &v->wi_y, &v->wi_w, &v->wi_h);
  320.  
  321.     v->wtype = GENERIC_WIN;
  322.     v->extra = (void *)0;
  323.     v->icon_slot = -1;
  324.     v->flags = 0;
  325.  
  326.     v->draw = clear_win;
  327.     v->topped = top_win;
  328.     v->closed = close_win;
  329.     v->fulled = full_win;
  330.     v->sized = size_win;
  331.     v->moved = move_win;
  332.     v->arrowed = noslid;
  333.     v->hslid = noslid;
  334.     v->vslid = noslid;
  335.     v->keyinp = nokey;
  336.     v->mouseinp = nomouse;
  337.     v->iconify = iconify_win;
  338.     v->oldfulled = v->fulled;
  339.     v->oldmouse = nomouse;
  340.  
  341.     v->menu = 0;
  342.     v->infostr = 0;
  343.  
  344.     v->next = gl_winlist;
  345.     gl_winlist = v;
  346.     return v;
  347. }
  348.  
  349. WINDOW *
  350. open_window(v)
  351.     WINDOW *v;
  352. {
  353.     int wx, wy, ww, wh;
  354.  
  355.     if (v->wi_handle >= 0)        /* already open?? */
  356.         return v;
  357.  
  358.     v->wi_handle = wind_create(v->wi_kind, v->wi_fullx, v->wi_fully,
  359.                 v->wi_fullw, v->wi_fullh);
  360.  
  361.     if (v->wi_handle < 0)
  362.         return 0;
  363.  
  364.     wind_set(v->wi_handle, WF_BEVENT, 0x0000, 0, 0, 0);
  365.     if (v->wi_kind & NAME) {
  366.         if (v->wi_title)
  367.             wind_set(v->wi_handle, WF_NAME, v->wi_title);
  368.         else
  369.             wind_set(v->wi_handle, WF_NAME, "Untitled");
  370.     }
  371.     if (v->wi_kind & INFO) {
  372.         if (v->infostr) {
  373.             wind_set(v->wi_handle, WF_INFO, v->infostr);
  374.         } else {
  375.             wind_set(v->wi_handle, WF_INFO, "");
  376.         }
  377.     }
  378.  
  379.     wind_calc(WC_BORDER, v->wi_kind, v->wi_x, v->wi_y, v->wi_w, v->wi_h,
  380.         &wx, &wy, &ww, &wh);
  381.  
  382.     if (win_flourishes)
  383.         graf_growbox(wx + ww/2, wy + wh/2, gl_wbox ,gl_hbox,
  384.                  wx, wy, ww, wh);
  385.  
  386.     wind_open(v->wi_handle, wx, wy, ww, wh);
  387.  
  388.     (*v->topped)(v);
  389. /* set scroll bars, etc. correctly */
  390.     (*v->sized)(v, wx, wy, ww, wh);
  391.     return v;
  392. }
  393.  
  394. void
  395. close_window(v)
  396.     WINDOW *v;
  397. {
  398.     int i, dummy;
  399.  
  400.     if (v->wi_handle < 0)    /* already closed? */
  401.         return;
  402.  
  403.     wind_close(v->wi_handle);
  404.     if (win_flourishes)
  405.         graf_shrinkbox(v->wi_x + v->wi_w/2, v->wi_y + v->wi_h/2,
  406.             gl_wbox, gl_hbox, v->wi_x, v->wi_y, v->wi_w, v->wi_h);
  407.     wind_delete(v->wi_handle);
  408.     v->wi_handle = -1;
  409.  
  410. /* reset gl_topwin */
  411.     gl_topwin = 0;
  412.     wind_get(0, WF_TOP, &i, &dummy, &dummy, &dummy);
  413.     for (v = gl_winlist; v; v = v->next) {
  414.         if (v->wi_handle == i)
  415.             break;
  416.     }
  417.     if (v && !(v->flags & WICONIFIED))
  418.         (*v->topped)(v);
  419. }
  420.  
  421. /*
  422.  * destroy a window
  423.  */
  424.  
  425. void
  426. destroy_window(v)
  427.     WINDOW *v;
  428. {
  429.     WINDOW **ptr, *w;
  430.     extern void unloadmenu();
  431.  
  432.     if (v->wi_handle >= 0) {
  433.         close_window(v);
  434.     }
  435.  
  436.     if (v->wi_title)
  437.         free(v->wi_title);
  438.  
  439.     if (v->infostr)
  440.         free(v->infostr);
  441.  
  442. /* find v in the window list, and unlink it */
  443.     ptr = &gl_winlist;
  444.     w = *ptr;
  445.     while (w) {
  446.         if (w == v) {
  447.             *ptr = v->next;
  448.             break;
  449.         }
  450.         ptr = &w->next;
  451.         w = *ptr;
  452.     }
  453. /* maybe we should have an error here if v isn't found */
  454.  
  455.     free(v);
  456. }
  457.  
  458. /*
  459.  * redraw all parts of a window that lie within the rectangle
  460.  * xc, yc, wc, hc
  461.  */
  462.  
  463. void
  464. redraw_window(v, xc, yc, wc, hc)
  465.     WINDOW *v;
  466.     int xc, yc, wc, hc;
  467. {
  468.     GRECT    t1, t2;
  469.     int temp[4];
  470.  
  471.     wind_update(TRUE);
  472.     hide_mouse();
  473.     t2.g_x = xc;
  474.     t2.g_y = yc;
  475.     t2.g_w = wc;
  476.     t2.g_h = hc;
  477.     wind_get(v->wi_handle, WF_FIRSTXYWH,
  478.          &t1.g_x, &t1.g_y, &t1.g_w, &t1.g_h);
  479.  
  480.     while (t1.g_w && t1.g_h) {
  481.         if (rc_intersect(&t2, &t1)) {
  482.             temp[0] = t1.g_x;
  483.             temp[1] = t1.g_y;
  484.             temp[2] = temp[0]+t1.g_w-1;
  485.             temp[3] = temp[1]+t1.g_h-1;
  486.             vs_clip(vdi_handle, 1, temp);
  487.             (*v->draw)(v, t1.g_x, t1.g_y, t1.g_w, t1.g_h);
  488.           }
  489.         wind_get(v->wi_handle, WF_NEXTXYWH, &t1.g_x, &t1.g_y,
  490.              &t1.g_w, &t1.g_h);
  491.     }
  492.     show_mouse();
  493.     wind_update(FALSE);
  494. }
  495.  
  496. /*
  497.  * find a window
  498.  */
  499.  
  500. WINDOW *
  501. which_window(x)
  502.     int x;
  503. {
  504.     WINDOW *w;
  505.  
  506.     if (x < 0) return 0;
  507.  
  508.     for (w = gl_winlist; w; w = w->next)
  509.         if (w->wi_handle == x)
  510.             return w;
  511.     return 0;
  512. }
  513.  
  514. /*
  515.  * handle an evnt_multi message dealing with windows
  516.  */
  517.  
  518. void
  519. handle_window(msgbuff)
  520.     int *msgbuff;
  521. {
  522.     WINDOW *v;
  523.  
  524.     v = which_window(msgbuff[3]);
  525.     if (!v) {    /* hmmm, not our window? */
  526.         return;
  527.     }
  528.  
  529.     switch(msgbuff[0]) {
  530.     case WM_REDRAW:
  531.         redraw_window(v, msgbuff[4], msgbuff[5], msgbuff[6], msgbuff[7]);
  532.         break;
  533.     case WM_TOPPED:
  534.         (*v->topped)(v);
  535.         break;
  536.     case WM_SIZED:
  537.         (*v->sized)(v, msgbuff[4], msgbuff[5], msgbuff[6], msgbuff[7]);
  538.         break;
  539.     case WM_MOVED:
  540.         (*v->moved)(v, msgbuff[4], msgbuff[5], msgbuff[6], msgbuff[7]);
  541.         break;
  542.     case WM_FULLED:
  543.         (*v->fulled)(v);
  544.         break;
  545.     case WM_ARROWED:
  546.         (*v->arrowed)(v, msgbuff[4]);
  547.         break;
  548.     case WM_HSLID:
  549.         (*v->hslid)(v, msgbuff[4]);
  550.         break;
  551.     case WM_VSLID:
  552.         (*v->vslid)(v, msgbuff[4]);
  553.         break;
  554.     case WM_CLOSED:
  555.         (*v->closed)(v);
  556.         break;
  557.     }
  558. }
  559.  
  560. int
  561. window_key(keycode, shift)
  562.     int keycode, shift;
  563. {
  564.     MENU *m;
  565.     ENTRY *e;
  566.     WINDOW *w;
  567.  
  568.     w = focuswin;    /* set in evnt_loop */
  569.  
  570.     if (w) {
  571. /* first, check for window specific menu shortcut keys */
  572.         for (m = w->menu; m; m = m->next) {
  573.             for (e = m->contents; e; e = e->next) {
  574.                 if (e->keycode == keycode) {
  575.                     (*e->func)(e->arg);
  576.                     return 1;
  577.                 }
  578.             }
  579.         }
  580.  
  581. /* otherwise, pass the key along to the general window handling thing */
  582.         return (*w->keyinp)(w, keycode, shift);
  583.     }
  584.     else
  585.         return 0;
  586. }
  587.  
  588. int
  589. window_click(clicks, x, y, kshift, mbutton)
  590.     int clicks, x, y, kshift, mbutton;
  591. {
  592.     WINDOW *w;
  593.  
  594. /* find the window that got clicked in (if any) */
  595.     w = find_window(x, y);
  596.     if (w) {
  597.         return (*w->mouseinp)(w, clicks, x, y, kshift, mbutton);
  598.     }
  599.     return 0;
  600. }
  601.  
  602. /*
  603.  * close and delete all windows
  604.  */
  605.  
  606. void
  607. end_windows()
  608. {
  609.     WINDOW *v;
  610.  
  611.     v = gl_winlist;
  612.     while (v) {
  613.         gl_winlist = v->next;
  614.         if (v->wi_handle >= 0) {
  615.             wind_close(v->wi_handle);
  616.             wind_delete(v->wi_handle);
  617.         }
  618.         free(v);
  619.         v = gl_winlist;
  620.     }
  621. }
  622.  
  623. /*
  624.  * force a redraw of a whole window
  625.  */
  626.  
  627. void
  628. force_redraw(v)
  629.     WINDOW *v;
  630. {
  631.     redraw_window(v, v->wi_x, v->wi_y, v->wi_w, v->wi_h);
  632.     if (v->wtype == TEXT_WIN)
  633.         mark_clean(v->extra);
  634. }
  635.  
  636. /*
  637.  * find out which window lies under the point (x,y). Returns a pointer
  638.  * to the window, or NULL
  639.  */
  640.  
  641. WINDOW *
  642. find_window(x, y)
  643.     int x, y;
  644. {
  645.     int wx, wy, ww, wh;
  646.     WINDOW *w;
  647.  
  648.     wind_update(1);    /* lock the screen -- we don't want it changing */
  649.     for (w = gl_winlist; w; w = w->next) {
  650.         if (w->wi_handle < 0) continue;
  651.         wind_get(w->wi_handle, WF_FIRSTXYWH, &wx, &wy, &ww, &wh);
  652.         while (ww && wh) {
  653.             if (x >= wx && x <= wx + ww &&
  654.                 y >= wy && y <= wy + wh)
  655.                 goto found_window;
  656.             wind_get(w->wi_handle, WF_NEXTXYWH, &wx, &wy, &ww, &wh);
  657.         }
  658.     }
  659. found_window:
  660.     wind_update(0);
  661.     return w;    /* w will be null if no window found */
  662. }
  663.  
  664. void
  665. change_window_gadgets(w, newkind)
  666.     WINDOW *w;
  667.     int newkind;
  668. {
  669.     int reopen = 0;
  670.     int nx, ny, nw, nh;
  671.     int oldflourishes;
  672.  
  673.     if (newkind == w->wi_kind) return;    /* no change */
  674.  
  675.     oldflourishes = win_flourishes;
  676.     win_flourishes = 0;
  677.  
  678.     if (w->wi_handle >= 0) {
  679.         wind_close(w->wi_handle);
  680.         wind_delete(w->wi_handle);
  681.         w->wi_handle = -1;
  682.         reopen = 1;
  683.     }
  684.  
  685.     wind_calc(WC_WORK, w->wi_kind, w->wi_fullx, w->wi_fully, w->wi_fullw,
  686.             w->wi_fullh, &nx, &ny, &nw, &nh);
  687.     wind_calc(WC_BORDER, newkind, nx, ny, nw, nh, &nx,
  688.             &ny, &w->wi_fullw, &w->wi_fullh);
  689.  
  690.     if (w->wi_fullw > wdesk)
  691.         w->wi_fullw = wdesk;
  692.     if (w->wi_fullh > hdesk)
  693.         w->wi_fullh = hdesk;
  694.  
  695.     if (w->wi_fullx < xdesk)
  696.         w->wi_fullx = xdesk;
  697.     if (w->wi_fully < ydesk)
  698.         w->wi_fully = ydesk;
  699.  
  700.     wind_calc(WC_BORDER, w->wi_kind, w->wi_x, w->wi_y, w->wi_w, w->wi_h,
  701.             &nx, &ny, &nw, &nh);
  702.     if (nw > w->wi_fullw)
  703.         nw = w->wi_fullw;
  704.     if (nh > w->wi_fullh)
  705.         nh = w->wi_fullh;
  706.  
  707.     wind_calc(WC_WORK, newkind, nx, ny, nw, nh, &w->wi_x, &w->wi_y,
  708.             &w->wi_w, &w->wi_h);
  709.  
  710.     w->wi_kind = newkind;
  711.  
  712.     if (reopen) {
  713.         open_window(w);
  714.     }
  715.     win_flourishes = oldflourishes;
  716. }
  717.  
  718. /*
  719.  * new_topwin: reset the top window so that it doesn't match the current
  720.  * top window (if that's possible). If force == 0, then we allow the current
  721.  * window to remain on top, otherwise we pretend that no window is on
  722.  * top
  723.  */
  724.  
  725. void
  726. new_topwin(force)
  727.     int force;
  728. {
  729.     WINDOW *w;
  730.     int mbuf[8];
  731.  
  732.     w = gl_topwin;
  733.     if (!w) return;
  734.     for(;;) {
  735.         w = w->next;
  736.         if (!w) w = gl_winlist;
  737.         if (w->wi_handle >= 0 && !(w->flags & WICONIFIED)) break;
  738.         if (w == gl_topwin) break;
  739.     }
  740.     if (w != gl_topwin) {
  741.         mbuf[0] = WM_TOPPED;
  742.         mbuf[1] = gl_apid;
  743.         mbuf[2] = 0;
  744.         mbuf[3] = w->wi_handle;
  745.         mbuf[4] = mbuf[5] = mbuf[6] = mbuf[7] = 0;
  746.         appl_write(gl_apid, 16, mbuf);
  747.     } else if (force) {
  748.         gl_topwin = 0;
  749.     }
  750. }
  751.  
  752. /* set a window title */
  753.  
  754. void
  755. title_window(w, title)
  756.     WINDOW *w; char *title;
  757. {
  758.     if (w->wi_title)
  759.         free(w->wi_title);
  760.     w->wi_title = strdup(title);
  761.     if (w->wi_handle >= 0 && (w->wi_kind & NAME)) {
  762.         wind_set(w->wi_handle, WF_NAME, w->wi_title);
  763.     }
  764. }
  765.